<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Vue Demo :-)</title>
    <style>
        html {
            background-color: #ddd;
        }

        #app1 {
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
        }

        .border {
            border: 1px solid rgb(122, 122, 122);
            margin-top: 40px;
            padding: 40px;
            position: relative;
            cursor: default;
            user-select: none;
            -webkit-user-select: none;
            background-color: #fff;
        }

        .row {
            display: flex;
        }

        .arrow-cell {
            display: flex;
            justify-content: center;
            align-items: center;
            box-sizing: border-box;
            width: 40px;
            height: 40px;

        }

        .arrow {
            font-weight: bold;
            font-size: 0.8em;
            transform: rotate(90deg);
        }
    </style>

</head>

<body>
    <div id='app1'>
        <div @mousedown='wow' @mouseup='haha' @mousemove='mousemove' @mouseleave='leave' class="border" ref='border'>
            <div :key='item' v-for='item in 13' class="row">
                <arrow-cell :key='item' v-for='item in 13' :post='post'></arrow-cell>
            </div>
        </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script>

        function calculate_deg(c1, c2, r1, r2) {
            r1 = r1 - c1;
            r2 = r2 - c2;
            const arc = Math.atan2(r1, r2);
            return Math.floor(arc / Math.PI * 180) + 180;
        }

        function random(b, e) {
            return Math.floor(Math.random() * (e - b + 1) + b);
        }

        document.oncontextmenu = function (e) {
            e.preventDefault();
        }

        class RandomRotate {
            constructor() {
                this.dire = random(0, 1) ? -1 : 1;
                this.speed = random(0, 30);
            }
            wander(fn, step) {
                let dire = this.dire;
                let speed = this.speed;
                this._stop = setInterval(() => {
                    step += (dire * speed);
                    if (step >= 360 && dire > 0) {
                        step = 0;
                    } else if (step <= 0 && dire < 0) {
                        step = 360
                    }
                    fn(step);
                }, 42) //每秒30帧
            }
            stop() {
                clearInterval(this._stop)
            }
        }

        Vue.component('arrow-cell', {
            props: ['post'],
            mounted() {
                this.center.wander = new RandomRotate();
                let that = this;
                this.center.wander.wander(function (deg) {
                    that.styleobj.transform = 'rotate(' + deg + 'deg)'
                }, 90)
                this.center.top = this.$refs.cell.offsetTop + 20;
                this.center.left = this.$refs.cell.offsetLeft + 20;
            },
            data: function () {
                return {
                    center: {},
                    styleobj: {
                        transform: 'rotate(90deg)'
                    }
                }
            },
            watch: {
                post: {
                    handler: function () {
                        let deg = calculate_deg(this.center.top, this.center.left, this.post.top, this.post.left);
                        if (this.post.leave) {
                            let that = this;
                            this.center.wander.wander(function (deg) {
                                that.styleobj.transform = 'rotate(' + deg + 'deg)'
                            }, deg)
                        } else {
                            this.center.wander.stop();
                            this.styleobj.transform = 'rotate(' + deg + 'deg)'
                        }
                    },
                    deep: true
                },
            },
            template: '<div ref="cell" class="arrow-cell"> <div v-bind:style="styleobj" class="arrow">{{ post.face ? post.face : "(-:" }}</div></div>'
        })

        new Vue({
            el: "#app1",
            data: {
                post: {
                    left: 0,
                    top: 0,
                    face: '',
                    leave: false
                }
            },
            methods: {
                mousemove: function (event) {
                    if (this.post.face !== '()-:' && this.post.face !== '←') {
                        this.post.face = ')-:'
                    }
                    this.post.leave = false;
                    let b = this.$refs.border;
                    this.post.left = event.x - b.offsetLeft;
                    this.post.top = event.y - b.offsetTop;
                },
                leave: function () {
                    this.post.face = '(-:'
                    this.post.leave = true;
                },
                wow: function (e) {
                    if (e.buttons === 1) {
                        this.post.face = '()-:'
                    } else {
                        this.post.face = '←';
                    }
                },
                haha: function () {
                    this.post.face = '';
                }
            },
        })
    </script>
</body>

</html>